<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=0.8">
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <!-- import CSS -->
    <link rel="stylesheet" href="./element-ui/index.css">
    <!-- import Vue before Element -->
    <script src="./element-ui/vue.js"></script>
    <!-- import JavaScript -->
    <script src="./element-ui/index.js"></script>
    <script src="./jquery-1.11.0.min.js"></script>
    <script src="./lightweight-charts.standalone.production.js"></script>
    <script src="./db.js"></script>
    <script src="./getData.js"></script>
    <script src="./factor.js"></script>
    <script src="./echarts.js"></script>
    <script src="./vue-chart.js"></script>
</head>
<body>
<!-- 列选择器 -->
<script type="text/x-template" id="use-column-template">
    <el-row>
        <el-col :span="24">
            <el-form :inline="true" size="mini">
                <el-form-item label="选择">
                    <el-checkbox-group v-model="column">
                        <el-select v-model="key" filterable allow-create default-first-option placeholder="首选项" style="width:120px;">
                            <el-option v-for="(col,index) in column" :key="index" :label="getName(col)" :value="col"></el-option>
                        </el-select>
                        <el-checkbox-button v-for="(col,index) in all" :key="index" :label="col">{{getName(col)}}
                        </el-checkbox-button>
                    </el-checkbox-group>
                </el-form-item>
            </el-form>
        </el-col>
    </el-row>
</script>
<script>
    //@ sourceMappingURL=use-column.js
    Vue.component('use-column', {
        props: ["all"],
        template: '#use-column-template',
        mounted: function () {
        },
        data: function () {
            return {
                key:"",
                column: []
            }
        },
        computed: {},
        methods: {
            getName: function (key) {
                return COLUMN_NAME[key] || key;
            },
            orderColumn: function (cols) {
                var arr = [];
                var my = this;

                if (null == cols) {
                    cols = my.column.slice();
                }

                for (var i = 0; i < my.all.length; i++) {
                    if (my.all[i] && cols.includes(my.all[i])) {
                        if (my.key != my.all[i]) {
                            arr.push(my.all[i]);
                        } else {
                            arr.unshift(my.all[i]);
                        }
                    }
                }
                arr.key = cols.key || my.key || my.column.key || arr[0];
                return arr;
            }
        },
        watch: {
            all: function () {
                var arr = this.all.slice();
                var my = this;
                DB.getTableRow("stock", my._uid || 0).then(function (col) {
                    if (col && col.value && col.value.length > 0) {
                        arr = my.orderColumn(col.value);
                        if (arr.length > 0) {
                            my.key = arr.key;
                            Vue.set(my, "column", arr);
                        }
                    }
                });
            },
            column: function (n) {
                if (n && n.length > 0) {
                    var arr = this.orderColumn(n);
                    this.$emit('update:use', arr);
                    DB.setTableRow("stock", {id: this._uid, value: arr});
                }
            },
            key: function (k) {
                if (k) {
                    var n = this.orderColumn();
                    this.$emit('update:use', n);
                    DB.setTableRow("stock", {id: this._uid, value: n});
                }
            },
        }
    });
</script>
<!-- echarts图表 -->
<script type="text/x-template" id="echarts-template">
    <div v-bind:style="style"></div>
</script>
<script>
    //@ sourceMappingURL=echarts.js
    Vue.component('echarts', {
        props: ["option", "width", "height"],
        template: '#echarts-template',
        mounted: function () {
            var chart = echarts.init(this.$el);
            //this.$emit('update:chart', chart);
            this.update = function(option) {
                chart.clear();
                chart.setOption(option);
            };
            if (this.option) {
                this.update(this.option);
            }
        },
        data: function () {
            return {
                style : {
                    width : this.width,
                    height : this.height
                }
            }
        },
        methods: {
        },
        watch: {
            option: function (val) {
                if (val) {
                    this.update(val);
                }
            },
        }
    });
</script>

<!-- scatter 散点图 -->
<script type="text/x-template" id="scatter-template">
    <el-row>
        <el-form :inline="true" size="mini">
            <el-form-item label="散点">
                <el-select v-model="chart.key" >
                    <el-option v-for="(col,index) in column" :key="index" :label="getName(col)" :value="col"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="散点X">
                <el-select v-model="chart.x" >
                    <el-option v-for="(col,index) in column" :key="index" :label="getName(col)" :value="col"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="散点Y">
                <el-select v-model="chart.y" >
                    <el-option v-for="(col,index) in column" :key="index" :label="getName(col)" :value="col"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-button type="success" size="mini" @click="show=!show">显示</el-button>
            </el-form-item>
        </el-form>
        <echarts v-if="show" :option="scatter" width="100%" height="480px"></echarts>
    </el-row>
</script>
<script>
    //@ sourceMappingURL=scatter.js
    Vue.component('scatter', {
        props: ["column", "value"],
        template: '#scatter-template',
        data: function () {
            return {
                show : false,
                chart : {
                    key: "",
                    x : "",
                    y : ""
                },
                scatter : this.getOption()
            }
        },
        methods: {
            getName: function (key) {
                return COLUMN_NAME[key] || key;
            },
            getOption : function () {
                if ((false == this.value) || (false == this.column)) {
                    return {};
                }

                var opt = {
                    visualMap: {
                        show: true,
                        min: -10,
                        max: 10,
                        dimension: 2,
                        inRange: {
                            color : ["#00AF64", "#FFD300", "#E40045"]
                            //color : ["#4671D5", "#FFFF40", "#FF4040"]
                            //color: ['#d94e5d','#eac736','#50a3ba'].reverse(),
                            //color: ['#ff0000','#ffff00','#0000ff'].reverse(),
                        },
                    },
                    xAxis: {
                        splitNumber: 20
                    },
                    yAxis: {
                        splitNumber: 20
                    },
                    series: [{
                        symbolSize: 5,
                        type: 'scatter',
                        data : []
                    }]
                };

                var max = Number.MIN_VALUE;
                var min = Number.MAX_VALUE;
                for (var i = 0; i < this.value.length; i++) {
                    var e = this.value[i];
                    try {
                        var data = e[this.chart.key]||0;
                        opt.series[0].data.push([e[this.chart.x], e[this.chart.y], e[this.chart.key]]);
                        if (data > max) {
                            max = data;
                        }
                        if (data < min) {
                            min = data;
                        }
                    } catch (err) {}
                }
                opt.visualMap.max = max;
                opt.visualMap.min = min;
                return opt;
            }
        },
        watch: {
            value: function (val) {
                if (val && this.show) {
                    this.scatter = this.getOption(val);
                }
            },
            show: function (val) {
                if (val) {
                    this.scatter = this.getOption();
                }
            },
            'chart.key': function () {
                if (this.show) {
                    this.scatter = this.getOption();
                }
            },
            'chart.x': function () {
                if (this.show) {
                    this.scatter = this.getOption();
                }
            },
            'chart.y': function () {
                if (this.show) {
                    this.scatter = this.getOption();
                }
            },
        }
    });
</script>

<!-- 表格 -->
<script type="text/x-template" id="stock-table-template">
    <el-row>
        <el-dialog title="详情" :visible.sync="dialogVisible" fullscreen>
            <el-col v-show="clickRow && more" :span="24">
                <el-form :inline="true" size="mini">
                    <el-form-item label="">
                        <el-button type="primary" size="mini" v-on:click="setUserStock(clickRow, true)">+自选</el-button>
                        <el-button type="primary" size="mini" v-on:click="setUserStock(clickRow, false)">-自选</el-button>
                    </el-form-item>
                </el-form>
                <slot v-bind:row="clickRow"></slot>
            </el-col>
        </el-dialog>
        <el-col v-show="clickRow && more" :span="24">
            <el-form :inline="true" size="mini">
                <el-form-item label="">
                    <el-button type="primary" size="mini" @click="clickRow=null">返回列表</el-button>
                    <el-button type="primary" size="mini" v-on:click="setUserStock(clickRow, true)">+自选</el-button>
                    <el-button type="primary" size="mini" v-on:click="setUserStock(clickRow, false)">-自选</el-button>
                </el-form-item>
            </el-form>
            <slot v-bind:row="clickRow"></slot>
        </el-col>
        <el-col v-show="null == clickRow" :span="24">
            <use-column :all="show" v-bind:use.sync="useColumn"></use-column>
            <el-pagination
                    :current-page="currentPage"
                    :page-size="page"
                    layout="total, prev, pager, next"
                    @current-change="currentChange"
                    :total="total">
            </el-pagination>
            <el-table :data="currentData" border stripe
                      :size="'mini'" @expand-change="expand" @sort-change="sort" @row-click="rowClick">
                <el-table-column v-for="(col,index) in useColumn" :key="index" :prop="col" :label="getName(col)"
                                 sortable>
                </el-table-column>
            </el-table>
        </el-col>
    </el-row>
</script>
<script>
    //@ sourceMappingURL=stock-table.js
    Vue.component('stock-table', {
        props: ["value", "show", "more", "select"],
        template: '#stock-table-template',
        mounted: function () {
        },
        data: function () {
            var page = 50;
            return {
                page: page,
                currentPage: 1,
                rawData: this.value,
                currentData: this.value.slice(0, page),
                selectData: [],
                clickRow: null,
                useColumn: [],
                dialogVisible: false
            }
        },
        computed: {
            total: function () {
                if (this.selectData.length > 0) {
                    return this.selectData.length;
                } else {
                    return this.rawData.length;
                }
            },
        },
        methods: {
            getName: function (key) {
                return COLUMN_NAME[key] || key;
            },
            expand: function (row) {
                if (typeof this.more == "function") {
                    this.more(row);
                }
            },
            setUserStock: function (row, set) {
                if (set) {
                    DB.setTableRow("user", row);
                } else {
                    DB.deleteTableRow("user", row.id);
                }
            },
            currentChange: function (val) {
                if (null == val) {
                    val = this.currentPage || 1;
                }
                this.currentPage = val;
                if (this.selectData.length > 0) {
                    Vue.set(this, "currentData", this.selectData.slice(val * this.page - this.page, val * this.page));
                } else {
                    Vue.set(this, "currentData", this.rawData.slice(val * this.page - this.page, val * this.page));
                }
            },
            sort: function (cond) {
                var desc = ("descending" == cond.order);

                function f(a, b) {
                    var a = a[cond.prop];
                    var da = parseFloat(a);
                    a = (da == a ? a : da);
                    var b = b[cond.prop];
                    var db = parseFloat(b);
                    b = (db == b ? b : db);
                    if (desc) {
                        return b > a ? 1 : -1;
                    } else {
                        return a > b ? 1 : -1;
                    }
                }

                this.rawData.sort(f);
                this.currentChange();
            },
            rowClick: function (row, column, event) {
                if (typeof this.more == "function") {
                    this.more(row);
                    this.clickRow = row;
                    //this.dialogVisible = true;
                }
            }
        },
        watch: {
            value: function (val) {
                this.clickRow = null;
                this.rawData = val;
                this.currentChange();
            },
            show: function () {
                this.useColumn = this.show.slice();
            },
            select: function (val) {
                if (val && val.length > 0) {
                    var arr = [];
                    for (var i = 0; i < val.length; i++) {
                        arr.push(this.rawData[val[i]]);
                    }
                    this.selectData = arr;
                } else {
                    this.selectData = [];
                }
                this.currentChange();
            }
        }
    });
</script>

<!-- main -->
<div id="app">
    <el-row>
        <el-col :span="24">
            <el-form :inline="true" size="mini">
                <el-radio-group v-model="listType" size="small">
                    <el-radio-button label="自选"></el-radio-button>
                    <el-radio-button label="问财"></el-radio-button>
                </el-radio-group>
                <el-form-item>
                    <el-autocomplete class="inline-input" v-model="stockList" style="width:360px;"
                                     :fetch-suggestions="queryStockList" placeholder="请输入问财条件">
                    </el-autocomplete>
                </el-form-item>
                <el-form-item label="股票数">
                    <span>{{listLength}}</span>
                </el-form-item>
            </el-form>
            <el-form :inline="true" size="mini">
                <el-form-item label="">
                    <el-select v-model="period" style="width:80px;">
                        <el-option label="日" value="101"></el-option>
                        <el-option label="60分" value="60"></el-option>
                        <el-option label="15分" value="15"></el-option>
                        <el-option label="5分" value="5"></el-option>
                        <el-option label="1分" value="1"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="">
                    <el-select v-model="dataLimit" style="width:80px;">
                        <el-option label="120" value="120"></el-option>
                        <el-option label="240" value="240"></el-option>
                        <el-option label="全部" value="1000000"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="">
                    <el-select v-model="calcCnt" style="width:80px;">
                        <el-option label="20" value="20"></el-option>
                        <el-option label="30" value="30"></el-option>
                        <el-option label="40" value="40"></el-option>
                        <el-option label="60" value="40"></el-option>
                        <el-option label="全部" value="1000000"></el-option>
                    </el-select>
                    <el-autocomplete class="inline-input" v-model="endDate" style="width:120px;"
                                     :fetch-suggestions="queryDateList" placeholder="请输入日期YYYYMMDD">
                    </el-autocomplete>
                </el-form-item>
                <el-form-item label="">
                    <el-select v-model="prevDays" filterable allow-create default-first-option style="width:80px;">
                        <el-option label="1" value="1"></el-option>
                        <el-option label="2" value="2"></el-option>
                        <el-option label="3" value="3"></el-option>
                        <el-option label="5" value="5"></el-option>
                        <el-option label="10" value="10"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button type="success" size="mini" @click="getStock(listType)">缓存选股</el-button>
                    <el-button type="primary" size="mini" @click="getStock(listType, true)">实时选股</el-button>
                    <el-button type="warning" size="mini" @click="getStock(listType, false, true)">回测</el-button>
                </el-form-item>
            </el-form>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="24">
            <use-column :all="table.showColumn" v-bind:use.sync="table.parseColumn"></use-column>
            <parallel :value="table.data" :column="table.parseColumn" :dimension="table.parseColumn.key" v-bind:selected.sync="table.selected"></parallel>
            <scatter :column="table.parseColumn" :value="table.data"></scatter>
            <stock-table :value="table.data" :show="table.showColumn" :more="expand" :select="table.selected">
                <template v-slot="props">
                    <el-row v-if="props.row">
                        <el-col :xl="24" :xs="24">
                            <el-card class="box-card">
                                <stock-chart :value="props.row"></stock-chart>
                            </el-card>
                        </el-col>
                    </el-row>
                </template>
            </stock-table>
        </el-col>
    </el-row>
</div>
</body>
<style>
    body {
        display: block;
        box-sizing: border-box;
        margin: 0px;
        padding: 0px;
    }

    .el-table__expanded-cell[class*=cell] {
        padding: 10px;
    }

    .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
        margin-bottom: 5px;
    }

    .el-table--mini td, .el-table--mini th {
        padding: 0px 0;
    }

    .el-tabs__header {
        margin: 0 0 5px 5px;
    }

    .el-table .cell {
        padding-right: 5px;
    }

    .el-table .cell, .el-table--border td:first-child .cell, .el-table--border th:first-child .cell {
        padding-left: 5px;
    }

    .el-form {
        margin: 0 5px;
    }
</style>
<script>
    var rootVm = new Vue({
        el: '#app',
        data: function () {
            return {
                listType: "问财",
                listLength: 0,
                prevDays: 3,
                stockList: BASE_STOCK[0],
                baseStockList: BASE_STOCK,
                stockFilter: BASE_FILTER[0],
                baseStockFilter: BASE_FILTER,
                factorList: FACTOR,
                period: "101",
                dataLimit: "120",
                calcCnt: "20",
                endDate: "20500101",
                filterFunc: "",
                currentPage: 1,
                useFactor: [],
                table: {
                    data: [],
                    showColumn: [],
                    parseColumn: [],
                    selected: []
                },
            }
        },
        methods: {
            getName: function (key) {
                return COLUMN_NAME[key] || key;
            },
            getStock: function (type, real, back) {
                var vm = this;
                var table = this.table;
                var period = this.period;
                var dataLimit = this.dataLimit;
                var endDate = this.endDate;
                var calcCnt = parseInt(this.calcCnt);
                var out = [];
                var parseOut = [];
                var list;
                if ("自选" == type) {
                    list = DB.getTable("user");
                } else {
                    list = fetchStockList(this.stockList);
                }
                table.data = [];
                table.showColumn = [];
                table.parseColumn = [];
                table.selected = [];
                list.then(function (list) {
                    Vue.set(table, "showColumn", getColumn("show"));
                    Vue.set(vm, "listLength", list.length);

                    for (var i = 0; i < list.length; i++) {
                        var s = getStockData(list[i], period, dataLimit, endDate, real);
                        s.then(function (arr) {
                            arr.index = i;
                            var d = formatData(arr, null, calcCnt, vm.prevDays);
                            if (back) {
                                for (var j = d.length - 1; j >= d.length - calcCnt; j--) {
                                    out.push(d[j]);
                                }
                            } else {
                                out.push(d[d.length - 1]);
                            }
                            Vue.set(table, "data", out);
                        })
                    }
                });
            },
            expand: function (row, exp) {
                /*
                row.currentPage = 1;
                row.dataReverse = formatData(row, null, row.data.length);
                row.dataReverse.reverse();
                 */
            },
            parse: function () {
                var parse = parseData(this.table.data, parseInt(this.prevDays), parseInt(this.calcCnt));
            },
            filter: function () {
                var all = getColumn();
                var filter = this.stockFilter;
                for (var i = 0; i < all.length; i++) {
                    var key = all[i];
                    var name = COLUMN_NAME[key];
                    if (null == name) {
                        continue;
                    }
                    filter = filter.replace(new RegExp("{" + name.replace(/[()]/g, "[()]") + "}", 'g'), "e." + key);
                }
                eval("function func(e){return " + filter + ";}");
                console.log(func);
                var arr = [];
                for (var i = 0; i < this.table.data.length; i++) {
                    if (func(this.table.data[i])) {
                        arr.push(i);
                    }
                }
                Vue.set(this.table, "selected", arr);
            },
            clearFilter: function () {
                Vue.set(this.table, "selected", []);
            },
            queryStockList: function (queryString, cb) {
                var arr = [];
                for (var i = 0; i < BASE_STOCK.length; i++) {
                    arr.push({"value": BASE_STOCK[i]});
                }
                cb(arr);
            },
            queryStockFilter: function (queryString, cb) {
                var arr = [];
                for (var i = 0; i < BASE_FILTER.length; i++) {
                    arr.push({"value": BASE_FILTER[i]});
                }
                cb(arr);
            },
            queryDateList: function (queryString, cb) {
                var arr = [];
                for (var i = 0; i < DATE_LIST.length; i++) {
                    arr.push({"value": DATE_LIST[i]});
                }
                cb(arr);
            },
        },
        watch: {
        }
    });
</script>
</html>